package com.sm.healthy.ui.fragment

import android.os.Bundle
import android.os.CountDownTimer
import android.widget.TextView
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import com.sm.healthy.utils.CacheUtil
import com.sm.healthy.R
import com.sm.healthy.base.BaseFragment
import com.sm.healthy.base.handle.TopHandle
import com.sm.healthy.data.bean.Spo2Entity
import com.sm.healthy.databinding.FragmentBloodPressureMeasurementBinding
import com.sm.healthy.device.MedicalProtocol
import com.sm.healthy.device.interfaces.Up_SPO2Listener
import com.sm.healthy.event.SerialPortDataMsgEvent
import com.sm.healthy.model.Spo2ViewModel
import com.sm.healthy.utils.DataUtils
import com.sm.healthy.utils.SerialPortUtil
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import me.hgj.jetpackmvvm.ext.nav
import me.hgj.jetpackmvvm.ext.navigateAction
import me.hgj.jetpackmvvm.ext.util.loge
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import java.util.*

/**
 * A simple [Fragment] subclass.
 * Use the [BloodPressureMeasurementFragment.newInstance] factory method to
 * create an instance of this fragment.
 */
class BloodPressureMeasurementFragment :
    BaseFragment<Spo2ViewModel, FragmentBloodPressureMeasurementBinding>(), Up_SPO2Listener {

    private val spo2Buf by lazy(LazyThreadSafetyMode.NONE) {
        arrayListOf<Int>()
    }
    private val pulseRateBuf by lazy(LazyThreadSafetyMode.NONE) {
        arrayListOf<Int>()
    }
    private val medicalProtocol by lazy(LazyThreadSafetyMode.NONE) {
        MedicalProtocol()
    }

    private var j = 0
    private val countDownTimer by lazy(LazyThreadSafetyMode.NONE) {
        object : CountDownTimer(60_000L, 1_000L) {
            override fun onTick(millisUntilFinished: Long) {

            }

            override fun onFinish() {
                stopMeasure()
                dealData()
                isStart = false
            }

        }
    }

    override fun layoutId(): Int {
        return R.layout.fragment_blood_pressure_measurement
    }

    override fun initView(savedInstanceState: Bundle?) {
        EventBus.getDefault().register(this)
        mDatabind.spo2Model = mViewModel
        mDatabind.click = Click()
        mDatabind.handle = TopHandle(nav())

        medicalProtocol.setSpo2Listener(this)
    }

    var isStart = false
    var isLeadOff = false//导联是否脱落
    var isDeviceOff = false //设备是否断开

    inner class Click {
        fun startMeasureBloodPressure() {
            isStart = isStart.not()
            if (isStart) {
                startMeasure()
            } else {
                countDownTimer.cancel()
                countDownTimer.onFinish()
            }
        }

        fun goHistory() {
            if (isStart) return mViewModel.toast.postValue("请先停止测量")
            nav().navigateAction(R.id.historyDataFragment)
        }
    }

    /**
     * 开始测量
     */
    private fun startMeasure() {
        countDownTimer.start()
        mDatabind.textView5.text = "停止测量"
        mDatabind.textView5.setBackgroundResource(R.drawable.bg_btn_red_shape)
    }

    private fun stopMeasure() {
        mDatabind.textView5.text = "开始测量"
        mViewModel.spo2Text.set("---")
        mViewModel.pulseRateText.set("---")
        mDatabind.textView5.setBackgroundResource(R.drawable.bg_btn_blue_shape)
    }

    override fun onSPO2_Wave(wave: Int, status: Int) {
        "wave: $wave status: $status".loge("csw")
        if (isStart.not()) return
        lifecycleScope.launch(Dispatchers.Main) {
            if (status > 0) {
                if (!isLeadOff) {
                    mViewModel.toast.postValue("血氧夹脱落，请检查...")
                    mViewModel.spo2Text.set("---")
                    mViewModel.pulseRateText.set("---")
                }
                isLeadOff = true

            } else {
                if (isDeviceOff) {
                    //有数据代表设备连接成功
                    mViewModel.toast.postValue(getString(R.string.device_connect_success))
                    onDeviceStatusChange(false)
                }
                if (isLeadOff) {
                    isLeadOff = false
                }
            }
            mDatabind.actSpoEcg.pointIntArr[j] = wave
            j++
            if (j >= 500) {
                j = 0
            }
            mDatabind.actSpoEcg.mTag = true
        }
    }

    override fun onSPO2_PR(spo2: Int, pulseRate: Int) {
        if (isStart.not()) return
        if (spo2 > 0 && pulseRate > 0) {
            mViewModel.spo2Text.set(spo2.toString())
            mViewModel.pulseRateText.set(pulseRate.toString())
            pulseRateBuf.add(pulseRate)
            spo2Buf.add(spo2)
            when {
                spo2 <= 90 -> {
                    mDatabind.tvSpo2.changeLevel(3)
                }
                spo2 in 91..93 -> {
                    mDatabind.tvSpo2.changeLevel(1)
                }
                spo2 >= 94 -> {
                    mDatabind.tvSpo2.changeLevel(0)
                }
            }
            when {
                pulseRate <= 60 -> {
                    mDatabind.tvPulseRateText.changeLevel(1)
                }
                pulseRate in 61..99 -> {
                    mDatabind.tvPulseRateText.changeLevel(0)
                }
                pulseRate >= 100 -> {
                    mDatabind.tvPulseRateText.changeLevel(2)
                }
            }
        }
    }

    /**
     * 改变设备状态
     *
     * @param isOff 设备是否断开
     */
    private fun onDeviceStatusChange(isOff: Boolean) {
        isDeviceOff = isOff
        if (isOff) {
            countDownTimer.cancel()
        }
        if (isLeadOff) {
            mViewModel.toast.postValue("血氧夹脱落，请检查...")
        }
    }

    @Subscribe(threadMode = ThreadMode.POSTING)
    fun onGetMsg(serialPortDataMsgEvent: SerialPortDataMsgEvent) {
        when (serialPortDataMsgEvent.getAction()) {
            SerialPortUtil.ACTION_SERIAPORT_READ -> {
                val data: ByteArray = serialPortDataMsgEvent.data
                val size: Int = serialPortDataMsgEvent.size
                medicalProtocol.Resolve(data, 0, size)
            }
        }
    }

    override fun onDestroy() {
        medicalProtocol.setSpo2Listener(null)
        super.onDestroy()
        EventBus.getDefault().unregister(this)
    }

    override fun onStop() {
        super.onStop()
        countDownTimer.cancel()
    }


    private fun dealData() {
        //去掉一个最大值和最小值
        if (spo2Buf.size < 3) {
            clear()
            return mViewModel.toast.postValue("数据过少，保存失败！")
        }
        if (pulseRateBuf.size < 3) {
            clear()
            return mViewModel.toast.postValue("数据过少，保存失败！")
        }
        spo2Buf.remove(Collections.max(spo2Buf))
        spo2Buf.remove(Collections.min(spo2Buf))
        pulseRateBuf.remove(Collections.max(pulseRateBuf))
        pulseRateBuf.remove(Collections.min(pulseRateBuf))
        val spo2Ave: Int = DataUtils.getAve(spo2Buf)
        val pulseRateAve: Int = DataUtils.getAve(pulseRateBuf)
        //TODO 储存血氧数据

        mViewModel.spo2Entity.value?.spo2Ave = spo2Ave
        mViewModel.spo2Entity.value?.pulseRateAve = pulseRateAve

        when {
            spo2Ave <= 90 -> {
                mViewModel.spo2Entity.value?.levelSpo2 = 1
                mDatabind.tvSpo2.changeLevel(2)
            }
            spo2Ave in 91..93 -> {
                mViewModel.spo2Entity.value?.levelSpo2 = 0
                mDatabind.tvSpo2.changeLevel(1)
            }
            spo2Ave >= 94 -> {
                mViewModel.spo2Entity.value?.levelSpo2 = 2
                mDatabind.tvSpo2.changeLevel(0)
            }
        }
        when {
            pulseRateAve <= 60 -> {
                mViewModel.spo2Entity.value?.levelPulse = 1
                mDatabind.tvPulseRateText.changeLevel(1)
            }
            pulseRateAve in 61..99 -> {
                mViewModel.spo2Entity.value?.levelPulse = 0
                mDatabind.tvPulseRateText.changeLevel(0)
            }
            pulseRateAve >= 100 -> {
                mViewModel.spo2Entity.value?.levelPulse = 2
                mDatabind.tvPulseRateText.changeLevel(2)
            }
        }
        mViewModel.insert()
        clear()
    }

    private fun clear() {
        spo2Buf.clear()
        pulseRateBuf.clear()
        mViewModel.spo2Entity.value = Spo2Entity(CacheUtil.getCurUid())
        mDatabind.actSpoEcg.reset()
    }

}

fun TextView.changeLevel(level: Int) {
    isVisible = true
    when (level) {
        0 -> {
            this.text = "正常"
            this.setBackgroundResource(R.drawable.bg_btn_blue_shape)
        }
        1 -> {
            this.text = "偏低"
            this.setBackgroundResource(R.drawable.bg_btn_yellow_shape)
        }
        2 -> {
            this.text = "偏高"
            this.setBackgroundResource(R.drawable.bg_btn_red_shape)
        }
        3 -> {
            this.text = "过低"
            this.setBackgroundResource(R.drawable.bg_btn_red_shape)
        }
    }
}
